import esbuild from "esbuild";
import process from "node:process";
import builtins from 'builtin-modules';
import { copy } from 'esbuild-plugin-copy';
import { basename } from 'node:path';
import { sassPlugin } from 'esbuild-sass-plugin';
import { readdirSync } from "node:fs";
import { config } from "dotenv";

config();

const banner = `/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
`;

const prod = (process.argv[2] === 'production');
const dir = process.env.OUTDIR ? process.env.OUTDIR : "./build";

const map = {
    'src/main.ts': 'main',
    'src/scss/styles.scss': 'styles',
    'src/scss/layout/slides-extended.scss': 'css/slides-extended',
    'src/plugin/reveal.js-elapsed-time-bar/elapsed-time-bar.js': 'plugin/elapsed-time-bar/elapsed-time-bar',
    'src/plugin/load-mathjax.js': 'plugin/load-mathjax',
};

const resolveRevealJsPlugins = {
    name: 'resolveRevealJsPlugins',
    setup(build) {
        //
        build.onResolve({ filter: /^\/plugin\/.*.png/ }, args => {
            return { path: args.path, external: true }
        })

        // Mark all paths starting with "http://" or "https://" as external
        build.onResolve({ filter: /^https?:\/\// }, args => {
            return { path: args.path, external: true }
        })
    },
}

const themeDir = 'src/scss/theme/';
const files = readdirSync(themeDir);
for (const file of files) {
    if (file.endsWith('.scss')) {
        const source = themeDir + file;
        const target = `dist/theme/${basename(file).replaceAll('.scss', '')}`;
        map[source] = target;
    }
}

const entryPoints = Object.entries(map)
    .map(([k, v]) => {
        return { 'in': k, 'out': v };
    });

const parameters = {
    banner: {
        js: banner,
    },
    entryPoints,
    bundle: true,
    platform: 'node',
    external: [
        'obsidian',
        'electron',
        "codemirror",
        '@codemirror/language',
        '@codemirror/state',
        '@codemirror/view',
        'moment',
        ...builtins
    ],
    loader: {
        '.png': 'dataurl',
        '.woff': 'dataurl',
        '.woff2': 'dataurl',
        '.eot': 'dataurl',
        '.ttf': 'dataurl',
        '.svg': 'dataurl',
    },
    format: 'cjs',
    minify: prod,
    target: 'es2022',
    logLevel: "info",
    sourcemap: prod ? false : 'inline',
    treeShaking: true,
    outdir: dir,
    plugins: [
        resolveRevealJsPlugins,
        sassPlugin({
            filter: /.(s[ac]ss|css)$/,
            loadPaths: [
                'node_modules/reveal.js/css',
            ],
        }),
        copy({
            assets: {
                from: ['manifest.json'],
                to: ['./manifest.json']
            }
        }),
        copy({
            assets: {
                from: ['README.md'],
                to: ['./README.md']
            }
        }),
        copy({
            assets: {
                from: ['distVersion.json'],
                to: ['./distVersion.json']
            }
        }),
        copy({
            assets: {
                from: ['src/template/**/*'],
                to: ['./template/']
            }
        }),
        copy({
            assets: {
                from: ['node_modules/reveal.js/dist/**/*'],
                to: ['./dist/'],
            }
        }),
        copy({
            assets: {
                from: ['node_modules/reveal.js/css/**/*'],
                to: ['./dist/css/'],
                keepStructure: true
            }
        }),
        copy({
            assets: {
                from: ['src/scss/theme/source/fonts/**/*'],
                to: ['./dist/theme/fonts/'],
            }
        }),
        copy({
            assets: {
                from: ['node_modules/highlight.js/styles/vs2015.css'],
                to: ['./plugin/highlight/'],
            }
        }),
        copy({
            assets: {
                from: ['node_modules/@fortawesome/fontawesome-free/js/all.min.js'],
                to: ['./dist/fontawesome/'],
            }
        }),
        copy({
            assets: {
                from: [
                    'node_modules/reveal.js/plugin/**/*',
                ],
                to: ['./plugin/'],
                keepStructure: true
            }
        }),
        copy({
            assets: {
                from: ['node_modules/reveal.js-plugins/chalkboard/**/*'],
                to: ['./plugin/chalkboard/'],
            }
        }),
        copy({
            assets: {
                from: ['node_modules/chart.js/dist/chart.umd.js'],
                to: ['./plugin/chart/'],
            }
        }),
        copy({
            assets: {
                from: ['node_modules/reveal.js-plugins/chart/*'],
                to: ['./plugin/chart/'],
            }
        }),
        copy({
            assets: {
                from: ['node_modules/reveal.js-plugins/customcontrols/*'],
                to: ['./plugin/customcontrols/'],
                keepStructure: true
            }
        }),
        copy({
            assets: {
                from: ['node_modules/mathjax/es5/**/*'],
                to: ['./plugin/math/mathjax'],
                keepStructure: true
            }
        }),
        copy({
            assets: {
                from: ['node_modules/reveal.js-menu/*'],
                to: ['./plugin/menu/'],
            }
        }),
        copy({
            assets: {
                from: ['node_modules/reveal.js-mermaid-plugin/plugin/mermaid/*'],
                to: ['./plugin/mermaid/'],
            }
        }),
        copy({
            assets: {
                from: [
                    'node_modules/reveal.js-pointer/dist/pointer.js',
                    'node_modules/reveal.js-pointer/dist/pointer.css',
                ],
                to: ['./plugin/reveal-pointer/'],
            }
        }),
        copy({
            assets: prod ? {} : {
                from: ['.hotreload'],
                to: ['.hotreload'],
            },
            once: true
        }),
    ],
};

if (prod) {
    await esbuild.build(parameters).catch((x) => {
        if (x.errors) {
            console.error(x.errors);
        } else {
            console.error(x);
        }
        process.exit(1)
    });
} else {
    const ctx = await esbuild.context(parameters);
    await ctx.watch();
}
